package com.sghd.fight.module.game.service.skill;

import com.sghd.fight.module.game.core.model.Buff;
import com.sghd.fight.module.game.core.model.Unit;
import com.sghd.fight.module.game.service.skill.alter.AlterType;
import com.sghd.fight.module.game.service.skill.alter.AlterValue;
import com.sghd.pojo.fight.game.UnitValue;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 上下文对象
 */
public class Context {

    private Unit owner;

    /** 战斗单元的值变更 */
    private final Map<Unit, AlterValue> values;
    private final Map<Unit, Collection<Buff>> buffs;

    /** 构造方法 */
    public Context(Unit owner) {
        values = new HashMap<>();
        buffs = new HashMap<>();
        this.owner = owner;
    }

    /**
     * 合并缓存修改值
     * @param target
     * @param value
     */
    public void merge(Unit target, AlterValue value) {
        AlterValue current = loadOrCreateValue(target);
        current.merge(value);
    }

    /** 使上下文中的值变更全部生效 */
    public void effect() {
        for (Entry<Unit, AlterValue> entry : values.entrySet()) {
            Unit unit = entry.getKey();
            AlterValue value = entry.getValue();
            unit.addSource(owner);
            value.effect(unit);
        }
        for (Entry<Unit, Collection<Buff>> entry : buffs.entrySet()) {
            Unit unit = entry.getKey();
            for (Buff buff : entry.getValue()) {
                unit.addBuff(buff);
            }
        }
    }

    /**
     * 使上下文中的指定战斗单元的值变更全部生效,并重置为空状态
     */
	public AlterValue effect(Unit owner) {
		AlterValue value = values.remove(owner);
		if (value != null) {
			value.effect(owner);
		}
		return value;
	}

    /**
     * 获取指定键的值，如果不存在则返回默认值
     * @param <E>
     * @param Fighter 单位
     * @param type 值修改类型
     * @param defaultValue 默认值
     * @param clz 值类型
     * @return
     */
    public <E> E getValue(Unit Fighter, AlterType type, E defaultValue, Class<E> clz) {
        AlterValue value = values.get(Fighter);
        if (value == null) {
            return defaultValue;
        }
        E result = value.getValue(type, clz);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 添加对指定战斗单元的属性变更值
     * @param target
     * @param type
     * @param value
     */
    public void addValue(Unit target, UnitValue type, Number value) {
        AlterType alterType = AlterType.getAlterType(type);
        AlterValue current = loadOrCreateValue(target);
        current.addValue(alterType, value);
    }

    public void addBuff(Unit target, Buff buff) {
        Collection<Buff> unitBuff = buffs.get(target);
        if (unitBuff == null) {
            unitBuff = new ArrayList<>();
            buffs.put(target, unitBuff);
        }
        unitBuff.add(buff);
    }
    // 内部方法

    /**
     * 加载或创建指定单位的临时值修改对象
     * @param target
     * @return
     */
    private AlterValue loadOrCreateValue(Unit target) {
        AlterValue result = values.get(target);
        if (result == null) {
            result = new AlterValue();
            values.put(target, result);
        }
        return result;
    }
}
